package com.bigShen.mybatis.official.plugin;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * @Author eddy.shen
 * @Date 2018/12/1 9:10
 **/
@Intercepts({
        @Signature(type = Executor.class,
            method = "query",
            args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
public class PluginSqlInfo implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        invocation.getMethod();
        invocation.getTarget();
        invocation.getClass();
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        String nameSpace = mappedStatement.getId();
        Object paramsValue = invocation.getArgs().length > 1 ? invocation.getArgs()[1] : null;
        BoundSql boundSql =  mappedStatement.getBoundSql(paramsValue);

        String sql = boundSql.getSql();
        List<ParameterMapping> paramKey = boundSql.getParameterMappings();

        StringBuffer paramsSql = new StringBuffer();
        Map<String, Object> valueMap = (Map<String, Object>) paramsValue;
        for (int i = 0; i< paramKey.size(); i++) {
            String key = paramKey.get(i).getProperty();
            paramsSql.append(key);
            paramsSql.append(" : ");
            paramsSql.append(valueMap.containsKey(key) ? valueMap.get(key) : null);
            paramsSql.append(", ");
        }

        System.out.println(String.format(" sql Type: %s \n NameSpace: %s \n Sql: %s;\n %s",
                sqlCommandType, nameSpace, sql, paramsSql.toString()));
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }

}
